#include "KMeansNetwork.h"

#include "../Utils/RandomUtil.h"
#include "../../inc/tinyxml2.h"

#include <fstream>

CKmeansNetwork::CKmeansNetwork(int inputDimension, int K, double variance, double kernelRandomMin, double kernelRandomMax) :
	m_K(K)
{
	auto randVectors = RandomUtil::CreateRandomVector(inputDimension, K, kernelRandomMin, kernelRandomMax);

	for (int i = 0; i < K; i++)
	{
		auto neuron = make_shared<CKMeansNeuron>(inputDimension, variance);
		neuron->InsertMeansPosition(randVectors[i]);

		this->m_KMeans.push_back(neuron);
	}
}

bool CKmeansNetwork::Save(const char * szFileName)
{
	tinyxml2::XMLDocument xmlDoc;

	xmlDoc.InsertFirstChild(xmlDoc.NewDeclaration());

	auto rootElement = xmlDoc.NewElement("K-Means");
	xmlDoc.InsertEndChild(rootElement);

	rootElement->SetAttribute("K-Value", this->m_K);

	std::ofstream csv;
	csv.open( string(szFileName) + ".csv");

	csv << "x,y" << std::endl;

	for (auto it = this->m_KMeans.begin(); it != this->m_KMeans.end(); ++it)
	{
		auto kmeansElement = xmlDoc.NewElement("K-MeansNeuron");
		CKMeansNeuron & neuron = *(*it);

		auto centerPoint = neuron.GetMeansPosition();
		kmeansElement->SetAttribute("CenterPoint", centerPoint.ToString().c_str());

		csv << centerPoint[0] << "," << centerPoint[1] << std::endl;

		auto kernelFunctionElement = xmlDoc.NewElement("KernelFunction");
		auto kernelObj = neuron.GetKernelFunctionObject();
		auto kernelFuncParams = kernelObj->Serialize();

		for (auto kpit = kernelFuncParams.begin(); kpit != kernelFuncParams.end(); ++kpit)
		{
			kernelFunctionElement->SetAttribute(kpit->first.c_str(), kpit->second.c_str());
		}

		kmeansElement->InsertEndChild(kernelFunctionElement);
		rootElement->InsertEndChild(kmeansElement);
	}

	xmlDoc.SaveFile(szFileName);

	return true;
}

bool CKmeansNetwork::Load(const char * szFileName)
{


	return true;
}

Vector CKmeansNetwork::Execute(Vector InputData)
{
	Vector FAI(this->m_K);

	for (int i = 0; i < this->m_K; i++)
	{
		FAI[i] = this->m_KMeans[i]->Execute(InputData);
	}

	return FAI;
}